class Traffic < ActiveRecord::Base
  attr_accessible :device, :flow, :start_at, :end_at
  belongs_to :device, polymorphic: true, :touch => :traffics_updated_at #:class_name => "Terminal", :foreign_key => "device_id"
  validates :device_id, :device_type, :end_at, presence: true

  default_scope where("device_id is not null and device_type is not null and start_at is not null and end_at is not null")

  # update traffic stat
  after_create do
    update_stat
  end

  scope :by_device_id, ->(device_id) do
    where(device_id: device_id)
  end
  # Todo(@Thomson->@Thomson): we should double check the time stuff, because the timezone may be mixed
  scope :after_date, lambda {|date| where(["traffics.end_at >= ?", date])}
  scope :before_date, lambda {|date| where(["traffics.end_at < ?", 1.days.since(Time.zone.parse(date)).strftime("%Y-%m-%d")])}

  # update traffic stat, including day, week, month
  def update_stat
    # update day stat
    key = TimeGroup.get_key 'day', end_at
    stat = TrafficStatDay.where(terminal_id: device.id, key: key).first_or_create(year: end_at.year, month: end_at.month, day: end_at.day, flow: 0)
    stat.update_attributes(flow: stat.flow + flow)

    # update week stat
    # ISO 8601 week-based year and week number:
    # The week 1 of YYYY starts with a Monday and includes YYYY-01-04.
    # The days in the year before the first week are in the last week of
    # the previous year.
    # see also: http://www.ruby-doc.org/core-1.9.3/Time.html#method-i-strftime
    key = TimeGroup.get_key 'week', end_at
    stat = TrafficStatWeek.where(terminal_id: device.id, key: key).first_or_create(year: end_at.strftime('%G').to_i, week: end_at.strftime('%V').to_i, flow: 0)
    stat.update_attributes(flow: stat.flow + flow)

    # update month stat
    key = TimeGroup.get_key 'month', end_at
    stat = TrafficStatMonth.where(terminal_id: device.id, key: key).first_or_create(year: end_at.year, month: end_at.month, flow: 0)
    stat.update_attributes(flow: stat.flow + flow)
  end
end
